package org.wattdepot.cli.processor;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.wattdepot.cli.command.CarbonContentCommand;
import org.wattdepot.cli.command.CarbonStatsCommand;
import org.wattdepot.cli.command.ChartCommand;
import org.wattdepot.cli.command.EnergyStatsCommand;
import org.wattdepot.cli.command.FuelTypeCommand;
import org.wattdepot.cli.command.PowerStatsCommand;
import org.wattdepot.cli.command.PowerCommand;
import org.wattdepot.cli.command.DailySensorDataCommand;
import org.wattdepot.cli.command.SensorDataCommand;
import org.wattdepot.cli.command.SourcesCommand;
import org.wattdepot.cli.command.SummaryCommand;
import org.wattdepot.cli.command.TotalCommand;
import org.wattdepot.cli.command.TotalPowerCommand;
import org.wattdepot.cli.command.WattDepotCliCommand;
import org.wattdepot.client.WattDepotClient;

/**
 * Tests the command processor class.
 * 
 * @author George Lee
 *
 */
public class TestCommandProcessor {
  /** The hostUri to the WattDepot instance.*/
  private String hostUri = "http://server.wattdepot.org:8182/wattdepot/";
  /** The instance of the WattDepot client.*/
  private WattDepotClient client;
  
  /**
   * Sets up the command processor test.
   */
  @Before
  public void setup() {
    this.client = new WattDepotClient(this.hostUri);
    // Stop right away if we cannot contact server.
    if (!client.isHealthy()) {
      System.out.println("Failed to connect to " + client.getWattDepotUri());
      fail("Could not instantiate client.");
    }
  }
  
  /**
   * Test that we can handle simple commands.
   */
  @Test
  public void testProcessCommand() {
    CommandProcessor processor = new CommandProcessor(this.client);

    // Test an unknown command.
    String result = processor.processCommand("foo");
    assertEquals("Checking invalid command", result, 
        WattDepotCliCommand.reportUnknownCommand("foo"));

    // Test the quit command.
    String oldResult = result;
    try {
      result = processor.processCommand("quit");
      fail("Testing that a runtime exception is thrown when we try to quit.");
    }
    catch (RuntimeException e) {
      // I hate that I had to put something in here, and it couldn't be "assertTrue(true)".
      assertEquals("Testing that no new output line was generated.", result, oldResult);
    }
  }
  
  /**
   * Makes sure the help results are correct.
   */
  @Test
  public void testHelpCommand() {
    CommandProcessor processor = new CommandProcessor(this.client);
    
    // Test the help command.
    List<WattDepotCliCommand> commands = new ArrayList<WattDepotCliCommand>();
    commands.add(new ChartCommand(this.client));
    commands.add(new PowerStatsCommand(this.client));
    commands.add(new PowerCommand(this.client));
    commands.add(new DailySensorDataCommand(this.client));
    commands.add(new SensorDataCommand(this.client));
    commands.add(new SourcesCommand(this.client));
    commands.add(new SummaryCommand(this.client));
    commands.add(new TotalCommand(this.client));
    commands.add(new CarbonContentCommand(this.client));
    commands.add(new FuelTypeCommand(this.client));
    commands.add(new TotalPowerCommand(this.client));
    commands.add(new CarbonStatsCommand(this.client));
    commands.add(new EnergyStatsCommand(this.client));
    
    String result = processor.processCommand("help");
    for (WattDepotCliCommand command : commands) {
      assertTrue("Testing that the help strings are correct.",
          result.contains(command.getHelp()));
    }
  }
  
  /**
   * Makes sure that the commands are executed properly in the command line. This is not to
   * verify that the commands are correct.
   */
  @Test
  public void testAvailableCommands() {
    CommandProcessor processor = new CommandProcessor(this.client);
    
    String command = "chart power generated SIM_OAHU_GRID 2009-09-01 2009-09-30 sampling-interval"
      + " 60 file kahe-september-energy.html";
    String result = processor.processCommand(command);
    assertFalse("Testing that the chart command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "total carbon generated SIM_OAHU_GRID day 2009-09-12 sampling-interval 120";
    result = processor.processCommand(command);
    assertFalse("Testing that the total command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "powerstats generated SIM_KAHE day 2009-09-30 sampling-interval 120 statistic max";
    result = processor.processCommand(command);
    assertFalse("Testing that the powerstats command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "power generated SIM_OAHU_GRID timestamp 2009-09-30T10:10:10.000-10:00";
    result = processor.processCommand(command);
    assertFalse("Testing that the power command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "dailysensordata SIM_KAHE_1 day 2009-09-30";
    result = processor.processCommand(command);
    assertFalse("Testing that the dailysensordata command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "sensordata SIM_KAHE_1 timestamp 2009-09-30T12:12:12.000-10:00";
    result = processor.processCommand(command);
    assertFalse("Testing that the sensordata command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "summary SIM_KAHE";
    result = processor.processCommand(command);
    assertFalse("Testing that the summary command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "sources";
    result = processor.processCommand(command);
    assertFalse("Testing that the sources command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "fueltypes SIM_IPP";
    result = processor.processCommand(command);
    assertFalse("Testing that the fuel types command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "totalpower SIM_IPP 2009-10-26T18:15:00.000-10:00 fueltype waste";
    result = processor.processCommand(command);
    assertFalse("Testing that the total power command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "carboncontent SIM_IPP 2009-11-15T12:00:00.000-10:00 sampling-interval 10";
    result = processor.processCommand(command);
    assertFalse("Testing that the carbon content command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "carbonstats SIM_OAHU_GRID from 2009-11-01 to 2009-11-02 stat max";
    result = processor.processCommand(command);
    assertFalse("Testing that the carbon stats command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
    
    command = "energystats generated SIM_OAHU_GRID from 2009-11-01 to 2009-11-02 daily";
    result = processor.processCommand(command);
    assertFalse("Testing that the energy stats command is processed.", 
        result.equals(WattDepotCliCommand.reportUnknownCommand(command)));
  }
}
